import { Component, Director, director, game } from "cc";
import Instance from "../Utils/Instance";

interface ITimer {
    tick: number;
    interval: number;
    repeat: number;
    func: Function;
    target: Object;
}

export default class TimerMgr extends Component {

    private _timers: ITimer[] = [];
    private _deltaTime: number = 0;
    public static get ins(): TimerMgr {
        return Instance.get(TimerMgr);
    }
    public get timers(): ITimer[] {
        return this._timers;
    }
    /**
     * 添加计时器
     * @param delay 间隔时间 
     * @param repeat 次数 -1无限循环
     * @param func 回调方法
     * @param target 回调主体对象
     * @returns 
     */
    public add(delay: number, repeat: number, func: Function, target: Object) {

        if (repeat == 0) {
            return;
        }

        this.remove(func, target);

        this._timers.push({
            tick: 0,
            interval: delay,
            repeat: repeat,
            func: func,
            target: target
        });
    }
    /**
     * 移除计时器
     * @param func 回调方法
     * @param target 回调主体对象
     */
    public remove(func: Function, target: Object) {
        for (let index = 0; index < this._timers.length; index++) {
            var element: ITimer = this._timers[index];
            if (element.func == func && element.target == target) {
                this._timers[index].func = null;
                break;
            }
        }
    }
    public removeAll(target: any) {
        for (let index = this._timers.length - 1; index >= 0; --index) {
            var element: ITimer = this._timers[index];
            if (element.target == target) {
                this._timers[index].func = null;
            }
        }
    }
    public init() {
        this._deltaTime = Date.now();
        director.on(Director.EVENT_BEFORE_UPDATE, this.befroeupdate, this);
    }
    public befroeupdate(): void {
        var deltaTime: number = Date.now() - this._deltaTime;
        for (let index = this._timers.length - 1; index >= 0; --index) {
            var element: ITimer = this._timers[index];
            element.tick += deltaTime;
            if (element.tick >= element.interval) {
                element.tick -= element.interval;
                if (element.func == null) {
                    this._timers.splice(index, 1);
                    continue;
                }
                element.func.call(element.target, element.repeat);
                if (element.repeat == -1) {
                    continue;
                }
                if (element.repeat > 0) {
                    element.repeat--;
                    if (element.repeat == 0) {
                        element.func = null;
                        continue;
                    }
                }
            }
        }
        this._deltaTime = Date.now();
    }
}
